﻿using movie.tool.library.hash;
using movie.tool.module.film.model;
using movie.tool.module.http;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace movie.tool.module.film.service
{
    public class MovieSynchronizer
    {
        private BusyInfo BusyInfo { get; set; }
        /// <summary>
        /// 当前编辑的剧本id
        /// </summary>
        private long EditMovieId { get; set; }
        /// <summary>
        /// 是否下载剧本文件.默认不下载
        /// </summary>
        public bool DownloadMovieFile { get; set; }
        public MovieSynchronizer(BusyInfo busyInfo, long editMovieId)
        {
            this.BusyInfo = busyInfo;
            this.EditMovieId = editMovieId;
        }

        private static ClueCardGroupConfig FindGroup(IEnumerable<ClueCardGroupConfig> groups, long id)
        {
            if (groups == null)
            {
                return null;
            }
            foreach (ClueCardGroupConfig group in groups)
            {
                if (group == null)
                {
                    continue;
                }
                if (group.Id == id)
                {
                    return group;
                }
            }
            return null;
        }

        public async Task<MovieProject> Synchronise()
        {
            BusyInfo.BusyMessage = "查询剧本基础信息...";
            MovieConfig movie = await HttpInvoker.GetAsync<MovieConfig>("movieserver/movies/" + EditMovieId);
            if (movie != null)
            {
                MovieProject localMovie = null;//MovieService.LoadProjectMovie(EditMovieId);
                if (localMovie == null)
                {
                    localMovie = new MovieProject();
                    localMovie.Id = EditMovieId;
                }
                localMovie.Movie = movie;
                BusyInfo.BusyMessage = "同步封面...";
                //封面图，如果本地有并且不一样,那就重新下载，如果一样，那就不用下载
                if (DownloadMovieFile)
                {
                    await SyncCoverFile(localMovie);
                    // 同步剧本手册
                    await SyncAssistFile(localMovie);
                }
                //同步剧幕
                await SyncMovieScenes(localMovie);
                BusyInfo.BusyMessage = "同步线索分组...";
                //同步线索分组
                await SyncClueCardGroups(localMovie);
                //同步线索
                BusyInfo.BusyMessage = "同步线索...";
                await SyncClueCards(localMovie);
                //同步角色
                BusyInfo.BusyMessage = "同步角色...";
                await SyncPlayerRole(localMovie);
                //同步电子书
                BusyInfo.BusyMessage = "同步电子书...";
                await SyncPlayRoleBook(localMovie);
                //同步完了，更新同步结果到本地文件
                MovieService.SaveProjectMovie(localMovie);
                return localMovie;
            }
            return null;
        }

        /// <summary>
        /// 同步封面图片
        /// </summary>
        /// <param name="localMovie">本地剧本配置对象</param>
        /// <returns></returns>
        public async Task SyncCoverFile(MovieProject localMovie)
        {
            string rootPath = MovieService.ProjectJsonFilePath(EditMovieId);
            string digest = await HttpInvoker.GetAsync<string>("movieserver/movies/" + EditMovieId + "/cover/digest");
            if (!string.IsNullOrEmpty(digest))
            {
                bool download = false;
                string filePath = Path.Join(rootPath, localMovie.Movie.Cover);
                if (File.Exists(filePath))
                {
                    string localDigest = SHA1Hash.FileDigest(filePath);
                    if (!digest.Equals(localDigest))
                    {
                        //文件不同,删除本地文件并下载远程文件
                        File.Delete(filePath);
                        download = true;
                    }
                }
                else
                {
                    download = true;
                }
                if (download)
                {
                    await HttpInvoker.DownloadFileAsync("movieserver/movies/" + EditMovieId + "/cover", filePath, false);
                }
            }
        }

        /// <summary>
        /// 同步剧本手册文件
        /// </summary>
        /// <param name="localMovie">本地剧本配置对象</param>
        /// <returns></returns>
        public async Task SyncAssistFile(MovieProject localMovie)
        {
            string rootPath = MovieService.ProjectJsonFilePath(EditMovieId);
            string digest = await HttpInvoker.GetAsync<string>("movieserver/movies/" + EditMovieId + "/assist/digest");
            if (!string.IsNullOrEmpty(digest))
            {
                bool download = false;
                string filePath = Path.Join(rootPath, localMovie.Movie.Assist);
                if (File.Exists(filePath))
                {
                    string localDigest = SHA1Hash.FileDigest(filePath);
                    if (!digest.Equals(localDigest))
                    {
                        //文件不同,删除本地文件并下载远程文件
                        File.Delete(filePath);
                        download = true;
                    }
                }
                else
                {
                    download = true;
                }
                if (download)
                {
                    await HttpInvoker.DownloadFileAsync("movieserver/movies/" + EditMovieId + "/assist", filePath, false);
                }
            }
        }

        public async Task<bool> ClearAssistFile()
        {
            return await HttpInvoker.DeleteAsync("movieserver/movies/" + EditMovieId + "/assist");
        }

        private async Task SyncMovieScenes(MovieProject localMovie)
        {
            BusyInfo.BusyMessage = "查询剧幕列表...";
            List<SceneConfig> scenes = await HttpInvoker.GetAsync<List<SceneConfig>>("movieserver/movieScenes/movie/" + EditMovieId);
            if (scenes != null && scenes.Count > 0)
            {
                if (DownloadMovieFile)
                {
                    string rootPath = MovieService.ProjectJsonFilePath(EditMovieId);
                    foreach (SceneConfig sc in scenes)
                    {
                        //同步每一幕的文件
                        await SyncScene(rootPath, sc);
                    }
                }
                localMovie.Scenes = new ObservableCollection<SceneConfig>(scenes);
            }
        }

        public async Task SyncScene(string rootPath, SceneConfig sc)
        {
            BusyInfo.BusyMessage = "同步剧幕:" + sc.Name;
            string digest = await HttpInvoker.GetAsync<string>("movieserver/movieScenes/" + sc.Id + "/digest");
            if (!string.IsNullOrEmpty(digest))
            {
                bool download = false;
                string filePath = Path.Join(rootPath, sc.File);
                if (File.Exists(filePath))
                {
                    string localDigest = SHA1Hash.FileDigest(filePath);
                    if (!digest.Equals(localDigest))
                    {
                        download = true;
                    }
                }
                else
                {
                    download = true;
                }
                if (download)
                {
                    if(!await HttpInvoker.DownloadObsFile("movieserver/movieScenes/" + sc.Id + "/obs", filePath))
                    {
                        await HttpInvoker.DownloadFileAsync("movieserver/movieScenes/" + sc.Id + "/file", filePath, false);
                    }
                }
            }
        }

        /// <summary>
        /// 同步线索分组
        /// </summary>
        /// <returns></returns>
        private async Task SyncClueCardGroups(MovieProject localMovie)
        {
            List<ClueCardGroupConfig> groups = await HttpInvoker.GetAsync<List<ClueCardGroupConfig>>("movieserver/clueCardGroups/movie/" + EditMovieId);
            localMovie.ClueCardGroups = groups != null && groups.Count > 0
                ? new ObservableCollection<ClueCardGroupConfig>(groups)
                : new ObservableCollection<ClueCardGroupConfig>();

        }

        private async Task SyncClueCards(MovieProject localMovie)
        {
            List<ClueCardConfig> clueCards = await HttpInvoker.GetAsync<List<ClueCardConfig>>("movieserver/clueCards/movie/" + localMovie.Id);
            if (clueCards == null || clueCards.Count <= 0)
            {
                return;
            }
            //
            string rootPath = MovieService.ProjectJsonFilePath(localMovie.Id);
            //同步线索文件
            foreach (ClueCardConfig clueCard in clueCards)
            {
                ClueCardGroupConfig group = FindGroup(localMovie.ClueCardGroups, clueCard.Group);
                if (group == null)
                {
                    //咋整
                    continue;
                }
                if (group.ClueCards == null)
                {
                    group.ClueCards = new ObservableCollection<ClueCardConfig>();
                }
                group.ClueCards.Add(clueCard);
                if (DownloadMovieFile)
                {
                    //标清文件
                    await syncClueCardSdFile(rootPath, clueCard);
                    //高清文件
                    await syncClueCardHdFile(rootPath, clueCard);
                }
            }
        }

        public static async Task syncClueCardHdFile(string rootPath, ClueCardConfig clueCard)
        {
            string digest = await HttpInvoker.GetAsync<string>("movieserver/clueCards/" + clueCard.Id + "/hdDigest");
            if (!string.IsNullOrEmpty(digest))
            {
                bool download = false;
                string filePath = Path.Join(rootPath, clueCard.HdFile);
                if (File.Exists(filePath))
                {
                    string localDigest = SHA1Hash.FileDigest(filePath);
                    if (!digest.Equals(localDigest))
                    {
                        download = true;
                    }
                }
                else
                {
                    download = true;
                }
                if (download)
                {
                    await HttpInvoker.DownloadFileAsync("movieserver/clueCards/" + clueCard.Id + "/hdFile", filePath, false);
                }
            }
        }

        public static async Task syncClueCardSdFile(string rootPath, ClueCardConfig clueCard)
        {
            string digest = await HttpInvoker.GetAsync<string>("movieserver/clueCards/" + clueCard.Id + "/sdDigest");
            if (!string.IsNullOrEmpty(digest))
            {
                bool download = false;
                string filePath = Path.Join(rootPath, clueCard.SdFile);
                if (File.Exists(filePath))
                {
                    string localDigest = SHA1Hash.FileDigest(filePath);
                    if (!digest.Equals(localDigest))
                    {
                        download = true;
                    }
                }
                else
                {
                    download = true;
                }
                if (download)
                {
                    await HttpInvoker.DownloadFileAsync("movieserver/clueCards/" + clueCard.Id + "/sdFile", filePath, false);
                }
            }
        }

        /// <summary>
        /// 同步角色信息
        /// </summary>
        /// <param name="localMovie"></param>
        /// <returns></returns>
        private async Task SyncPlayerRole(MovieProject localMovie)
        {
            List<PlayerRoleConfig> roles = await HttpInvoker.GetAsync<List<PlayerRoleConfig>>("movieserver/playRoles/movie/" + EditMovieId);
            if (roles != null && roles.Count > 0)
            {
                if (DownloadMovieFile)
                {
                    string rootPath = MovieService.ProjectJsonFilePath(EditMovieId);
                    //同步每个角色的文件
                    foreach (PlayerRoleConfig role in roles)
                    {
                        await SyncPlayRoleFile(rootPath, role);
                    }
                }
                localMovie.Roles = new ObservableCollection<PlayerRoleConfig>(roles);
            }
        }

        public static async Task SyncPlayRoleFile(string rootPath, PlayerRoleConfig role)
        {
            string digest = await HttpInvoker.GetAsync<string>("movieserver/playRoles/" + role.Id + "/digest");
            if (!string.IsNullOrEmpty(digest))
            {
                bool download = false;
                string filePath = Path.Join(rootPath, role.FilePath);
                if (File.Exists(filePath))
                {
                    string localDigest = SHA1Hash.FileDigest(filePath);
                    if (!digest.Equals(localDigest))
                    {
                        download = true;
                    }
                }
                else
                {
                    download = true;
                }
                if (download)
                {
                    await HttpInvoker.DownloadFileAsync("movieserver/playRoles/" + role.Id + "/file", filePath, false);
                }
            }
        }

        private async Task SyncPlayRoleBook(MovieProject localMovie)
        {
            List<BookChapter> chapters = await HttpInvoker.GetAsync<List<BookChapter>>("movieserver/chapters/movie/" + EditMovieId);
            if (chapters != null && chapters.Count > 0)
            {
                localMovie.Chapters = new ObservableCollection<BookChapter>(chapters);
            }
            else
            {
                localMovie.Chapters = new ObservableCollection<BookChapter>();
            }
            List<PlayRoleBookConfig> books = await HttpInvoker.GetAsync<List<PlayRoleBookConfig>>("movieserver/playRoleBooks/movie/" + EditMovieId);
            if (books != null && books.Count > 0)
            {
                //同步电子书文件
                if (DownloadMovieFile)
                {
                    string rootPath = MovieService.ProjectJsonFilePath(EditMovieId);
                    foreach (PlayRoleBookConfig book in books)
                    {
                        await SyncPlayRoleBook(rootPath, book);
                    }
                }
                localMovie.Books = new ObservableCollection<PlayRoleBookConfig>(books);
            }
        }

        public static async Task SyncPlayRoleBook(string rootPath, PlayRoleBookConfig book)
        {
            string digest = await HttpInvoker.GetAsync<string>("movieserver/playRoleBooks/" + book.Id + "/digest");
            if (!string.IsNullOrEmpty(digest))
            {
                bool download = false;
                string filePath = Path.Join(rootPath, book.FilePath);
                if (File.Exists(filePath))
                {
                    string localDigest = SHA1Hash.FileDigest(filePath);
                    if (!digest.Equals(localDigest))
                    {
                        download = true;
                    }
                }
                else
                {
                    download = true;
                }
                if (download)
                {
                    await HttpInvoker.DownloadFileAsync("movieserver/playRoleBooks/" + book.Id + "/file", filePath, false);
                }
            }
        }
    }
}
